<template>
  <div class="process-panel__container" :style="{ width: `${this.width}px` }">
    <el-collapse v-model="activeTab">
      <el-collapse-item name="base">
        <div slot="title" class="panel-tab__title"><i class="el-icon-setting"></i>基本设置</div>
        <element-base-info :id-edit-disabled="idEditDisabled" :business-object="elementBusinessObject"
                           :type="elementType"
        />
      </el-collapse-item>
      <el-collapse-item name="compliance" key="compliance" v-if="formVisible">
        <div slot="title" class="panel-tab__title"><i class="el-icon-warning"></i>合规风险提示</div>
        <compliance-base-info :id="elementId" :id-edit-disabled="idEditDisabled"
                              :business-object="elementBusinessObject"
                              :type="elementType"
        />
      </el-collapse-item>
      <el-collapse-item name="form" key="form" v-if="formVisible">
        <div slot="title" class="panel-tab__title"><i class="el-icon-document"></i>节点表单</div>
        <!--        <element-form :id="elementId" :type="elementType" v-show="false"/>-->
        <form-file :id="elementId" :id-edit-disabled="idEditDisabled" :business-object="elementBusinessObject"
                   :type="elementType"
        />
      </el-collapse-item>
      <!--      <el-collapse-item name="system" key="system" v-if="formVisible">-->
      <!--        <div slot="title" class="panel-tab__title"><i class="el-icon-user"></i>制度文件</div>-->
      <!--        <system-form :id="elementId" :id-edit-disabled="idEditDisabled" :business-object="elementBusinessObject"-->
      <!--                     :type="elementType"-->
      <!--        />-->
      <!--      </el-collapse-item>-->
      <el-collapse-item name="correlation" key="correlation"
                        v-if="elementType.indexOf('ScriptTask') !== -1"
      >
        <div slot="title" class="panel-tab__title"><i class="el-icon-s-operation"></i>关联流程</div>
        <correlation-base-info id="elementId" :type="elementType" :business-object="elementBusinessObject"
                               @update="updateHandle"
        />
      </el-collapse-item>
      <el-collapse-item name="task" v-if="elementType.indexOf('Task') !== -1" key="task">
        <div slot="title" class="panel-tab__title"><i class="el-icon-s-claim"></i>审批人设置</div>
        <element-task :id="elementId" :type="elementType"/>
      </el-collapse-item>
      <el-collapse-item name="multiInstance" key="multiInstance">
        <div slot="title" class="panel-tab__title"><i class="el-icon-s-help"></i>流程反馈</div>
        <feed-back :business-object="elementBusinessObject"></feed-back>
      </el-collapse-item>
    </el-collapse>
  </div>
</template>
<script>
import ElementBaseInfo from './base/ElementBaseInfo'
import ComplianceBaseInfo from './compliance/ComplianceBaseInfo'
import CorrelationBaseInfo from './correlation/CorrelationBaseInfo'
import ElementOtherConfig from './other/ElementOtherConfig'
import ElementTask from './task/ElementTask'
import ElementMultiInstance from './multi-instance/ElementMultiInstance'
import FlowCondition from './flow-condition/FlowCondition'
import SignalAndMassage from './signal-message/SignalAndMessage'
import ElementListeners from './listeners/ElementListeners'
import ElementProperties from './properties/ElementProperties'
// import ElementForm from './form/ElementForm'
import SystemForm from './system/SystemForm'
import UserTaskListeners from './listeners/UserTaskListeners'
import FormFile from './form/FormFile'
import { updateNode } from '@/api/workflow/model'
import FeedBack from './feedback/FeedBack'

/**
 * 侧边栏
 * @Author MiyueFE
 * @Home https://github.com/miyuesc
 * @Date 2021年3月31日18:57:51
 */
export default {
  name: 'BpmnPropertiesPanel',
  components: {
    UserTaskListeners,
    ElementProperties,
    ElementListeners,
    SignalAndMassage,
    FlowCondition,
    ElementMultiInstance,
    ElementTask,
    ElementOtherConfig,
    ElementBaseInfo,
    ComplianceBaseInfo,
    CorrelationBaseInfo,
    SystemForm,
    FormFile,
    FeedBack
  },
  componentName: 'BpmnPropertiesPanel',
  props: {
    bpmnModeler: Object,
    prefix: {
      type: String,
      default: 'camunda'
    },
    width: {
      type: Number,
      default: 480
    },
    idEditDisabled: {
      type: Boolean,
      default: false
    }
  },
  provide() {
    return {
      prefix: this.prefix,
      width: this.width
    }
  },
  data() {
    return {
      activeTab: 'base',
      elementId: '',
      elementType: '',
      elementBusinessObject: {}, // 元素 businessObject 镜像，提供给需要做判断的组件使用
      conditionFormVisible: false, // 流转条件设置
      formVisible: false // 表单配置
    }
  },
  watch: {
    elementId: {
      handler() {
        this.activeTab = 'base'
      }
    }
  },
  created() {
    this.initModels()
  },
  methods: {
    initModels() {
      // 初始化 modeler 以及其他 moddle
      if (!this.bpmnModeler) {
        // 避免加载时 流程图 并未加载完成
        this.timer = setTimeout(() => this.initModels(), 10)
        return
      }
      if (this.timer) clearTimeout(this.timer)
      window.bpmnInstances = {
        modeler: this.bpmnModeler,
        modeling: this.bpmnModeler.get('modeling'),
        moddle: this.bpmnModeler.get('moddle'),
        eventBus: this.bpmnModeler.get('eventBus'),
        bpmnFactory: this.bpmnModeler.get('bpmnFactory'),
        elementFactory: this.bpmnModeler.get('elementFactory'),
        elementRegistry: this.bpmnModeler.get('elementRegistry'),
        replace: this.bpmnModeler.get('replace'),
        selection: this.bpmnModeler.get('selection')
      }
      this.getActiveElement()
      setTimeout(() => {
        this.mainMethod()
      }, 1000)

    },
    mainMethod() {
      this.success()
    },
    getActiveElement() {
      // 初始第一个选中元素 bpmn:Process
      this.initFormOnChanged(null)
      this.bpmnModeler.on('import.done', e => {
        this.initFormOnChanged(null)
      })
      // 监听选择事件，修改当前激活的元素以及表单
      this.bpmnModeler.on('selection.changed', ({ newSelection }) => {
        this.initFormOnChanged(newSelection[0] || null)
      })
      this.bpmnModeler.on('element.changed', ({ element }) => {
        // 保证 修改 "默认流转路径" 类似需要修改多个元素的事件发生的时候，更新表单的元素与原选中元素不一致。
        if (element && element.id === this.elementId) {
          this.initFormOnChanged(element)
        }
      })
    },
    // 初始化数据
    initFormOnChanged(element) {
      console.log('初始化数据', element)
      let activatedElement = element
      if (!activatedElement) {
        activatedElement =
          window.bpmnInstances.elementRegistry.find(el => el.type === 'bpmn:Process') ??
          window.bpmnInstances.elementRegistry.find(el => el.type === 'bpmn:Collaboration')
      }
      if (!activatedElement) return
      if (activatedElement.type.split(':')[1] === 'Process') return
      console.log(`
              ----------
      select element changed:
                id:  ${activatedElement.id}
              type:  ${activatedElement.businessObject.$type}
              ----------
              `)
      console.log('businessObject: ', activatedElement.businessObject)
      window.bpmnInstances.bpmnElement = activatedElement
      this.bpmnElement = activatedElement
      this.elementId = activatedElement.id
      this.elementType = activatedElement.type.split(':')[1] || ''
      this.elementBusinessObject = JSON.parse(JSON.stringify(activatedElement.businessObject))
      console.log(this.elementBusinessObject)
      let elementRegistry = this.bpmnModeler.get('elementRegistry')
      let nodeKey = this.elementBusinessObject.id
      if (this.elementBusinessObject.$type === 'bpmn:UserTask' && nodeKey !== undefined) {
        console.log('nodeKey', nodeKey)
        let node = elementRegistry._elements[nodeKey]
        console.log('node', node)
        if (node !== undefined) {
          let nodeElement = node.element
          let data = this.elementBusinessObject.extensionElements
          if (nodeElement.type === 'bpmn:UserTask' && data !== undefined && data.values.length > 0) {
            console.log('data.values[0].values.length', data.values[0].values.length)
            for (let ii = 0; ii < data.values[0].values.length; ii++) {
              if (data.values[0].values[ii].name === 'compliance' && data.values[0].values[ii].value !== undefined) {
                node.gfx.childNodes[1].style.strokeOpacity = 1
                node.gfx.childNodes[1].style.stroke = 'red'
                node.gfx.childNodes[1].style.strokeWidth = '2px'
              }
            }
          }
        }
      }
      //
      // for (let key in elementRegistry._elements) {
      //   console.log('key', key)
      //
      // }
      this.conditionFormVisible = !!(
        this.elementType === 'SequenceFlow' &&
        activatedElement.source &&
        activatedElement.source.type.indexOf('StartEvent') === -1
      )
      this.formVisible = this.elementType === 'UserTask' || this.elementType === 'StartEvent'
      console.log('this.elementType ', this.elementType)
      if (this.elementType === 'Participant') {

      }
    },
    success() {
      // 重新初始化所有xml中导入元素的label和横线
      let elementRegistry = this.bpmnModeler.get('elementRegistry')
      console.log('--------elementRegistry-------', elementRegistry)
      for (let key in elementRegistry._elements) {
        let node = elementRegistry._elements[key]
        let element = node.element
        if (element.type === 'bpmn:Participant') {
          // 父泳道
          let laneLength = element.children.reduce((pre, cur) => cur.type === 'bpmn:Lane' ? ++pre : pre, 0)
          // 没有子泳道就不用设置
          if (laneLength > 0) {
            // 设置父级宽度, 以第一个子级 * 数量为准
            element.width = element.children[0].width * laneLength
          }
          // 设置label文字位置
          let chatWidth = node.gfx.childNodes[0].childNodes[0].getAttribute('width')
          let textWidth = node.gfx.childNodes[0].getElementsByTagName('text')[0].getElementsByTagName('tspan')[0].innerHTML.length * 14 / 2
          node.gfx.childNodes[0].getElementsByTagName('text')[0].getElementsByTagName('tspan')[0].setAttribute('x', (chatWidth - textWidth) / 2)
          // 设置label编辑框的点击位置
          node.gfx.getElementsByClassName('djs-hit-all')[0].setAttribute('width', node.element.width)
          node.gfx.getElementsByClassName('djs-hit-all')[0].setAttribute('height', 30)
          // 设置横线分割线位置
          if (node.gfx.childNodes[0].getElementsByTagName('polyline')[0]) {
            node.gfx.childNodes[0].getElementsByTagName('polyline')[0].setAttribute('points', '-30, 0, -30, ' + chatWidth)
          }
        } else if (element.type === 'bpmn:Lane' && element.parent.type === 'bpmn:Participant') {
          // 子泳道
          // 设置label文字位置
          let chatWidth = node.gfx.childNodes[0].childNodes[0].getAttribute('width')
          let textWidth = node.gfx.childNodes[0].getElementsByTagName('text')[0].getElementsByTagName('tspan')[0].innerHTML.length * 14 / 2
          node.gfx.childNodes[0].getElementsByTagName('text')[0].getElementsByTagName('tspan')[0].setAttribute('x', (chatWidth - textWidth) / 2)
          // 设置label编辑框的点击位置
          node.gfx.getElementsByClassName('djs-hit-all')[0].setAttribute('width', node.element.width)
          node.gfx.getElementsByClassName('djs-hit-all')[0].setAttribute('height', 30)
          // 设置label编辑框
          // console.log(node)
          // node.gfx.getElementsByClassName("djs-hit-all")[0].setAttribute("width", node.element.width)
          // node.gfx.getElementsByClassName("djs-hit-all")[0].setAttribute("height", 30)

          // 设置横线分割线位置
          if (node.gfx.childNodes[0].getElementsByTagName('polyline')[0]) {
            node.gfx.childNodes[0].getElementsByTagName('polyline')[0].setAttribute('points', '-30, 0, -30, ' + chatWidth)
          }

        }

        if (element.type === 'bpmn:ReceiveTask' || element.type === 'bpmn:BusinessRuleTask') {
          // let square = document.getElementsByClassName('djs-element djs-shape')[0]
          node.gfx.childNodes[0].getElementsByTagName('rect')[0].style.strokeWidth = 0
        }

        if (element.type === 'bpmn:UserTask') {
          this.initFormOnChanged(element)
        }

        if (element.type === 'bpmn:ScriptTask') {
          let textNode = node.gfx.getElementsByClassName('djs-visual')[0].querySelector('text')
          console.log('textNode', textNode)
          let txt = textNode.querySelectorAll('tspan')
          let node1 = ''
          for (let i = 0; i < txt.length; i++) {
            node1 = txt[i].innerHTML + node1
          }
          console.log('txt', txt)
          let x = txt[0].getAttribute('x')
          let y = txt[0].getAttribute('y')
          console.log('x', x)
          console.log('y', y)
          console.log('node1', node1)
          if (node1.length > 4) {
            console.log(node1.length)
            console.log(node1.length / 4)
            let forNum = node1.length % 4 === 0 ? parseInt(node1.length / 4) : parseInt(node1.length / 4) + 1
            console.log('forNum', forNum)
            let innerHTML = ''
            x = parseFloat(x) + 15
            y = parseFloat(y) - 15
            for (let i = 1; i <= forNum; i++) {
              let index1
              if (i === 1) {
                index1 = 0
              } else {
                index1 = (i - 1) * 4
                y = y + 15
              }
              let html
              let index2
              if (i === forNum) {
                index2 = node1.length
              } else {
                index2 = (i) * 4
              }
              html = '<tspan x="' + x + '" y="' + y + '">' + node1.slice(index1, index2) + '</tspan>'
              console.log('--------------------------html-')
              console.log(index1)
              console.log(index2)
              console.log(html)
              innerHTML = html + innerHTML
            }
            textNode.innerHTML = innerHTML
          }
          console.log('textNode.innerHTML', textNode.innerHTML)
        }
      }
      // 重新初始化所有泳道label修改名称时的text元素宽度
      for (let key in elementRegistry._elements) {
        let node = elementRegistry._elements[key]
        let element = node.element
        if (element.type === 'bpmn:Participant' || element.type === 'bpmn:Lane') {
          // let djsVisual = node.gfx.getElementsByClassName("djs-visual")[0]
          let textNode = node.gfx.getElementsByClassName('djs-visual')[0].lastElementChild
          textNode.innerHTML = ''
          let txt = this.bpmnModeler.get('bpmnRenderer')._renderLabel(textNode, element.businessObject.name, {
            box: {
              height: 30,
              width: element.width
            },
            align: 'center-middle',
            style: {
              fill: 'red'
            }
          })
          textNode.innerHTML = txt.innerHTML
        }
      }
      this.addEventBusListener()
      this.addModelerListener()
    },

    wrapWord(text, width) {
      text.each(function() {
        var text = d3.select(this),
          words = text.text().split('').reverse(),
          word,
          line = [],
          lineNumber = 0,
          lineHeight = text.node().getBoundingClientRect().height,
          x = +text.attr('x'),
          y = +text.attr('y'),
          tspan = text.text(null).append('tspan').attr('x', x).attr('y', y)
        while (word = words.pop()) {
          line.push(word)
          const dash = lineNumber > 0 ? '-' : ''
          tspan.text(dash + line.join(''))
          if (tspan.node().getComputedTextLength() > width) {
            line.pop()
            tspan.text(line.join(''))
            line = [word]
            tspan = text.append('tspan').attr('x', x).attr('y', ++lineNumber * lineHeight + y).text(word)
          }
        }
      })
    },

    addEventBusListener() {
      // 监听 element
      let that = this
      const eventBus = this.bpmnModeler.get('eventBus')
      const elementRegistry = this.bpmnModeler.get('elementRegistry')
      const eventTypes = ['element.create', 'element.click', 'element.dblclick', 'element.changed', 'element.updateLabel', 'import.parse.complete', 'directEditing.activate', 'directEditing.complete', 'drag.move']
      eventTypes.forEach(function(eventType) {
        eventBus.on(eventType, function(e) {
          if (!e || (e.element && e.element.type == 'bpmn:Process')) return
          if (eventType === 'element.changed') {
            try {
              // parent为null时, 为删除的元素, 不需要进行任何操作
              if (e.element.parent === null) {
                return
              }
              // 拖动子级时reset设置父级宽度及定位
              if (e.element.type === 'bpmn:Lane' && e.element.parent.type === 'bpmn:Participant') {
                let laneLength = e.element.parent.children.reduce((pre, cur) => cur.type === 'bpmn:Lane' ? ++pre : pre, 0)
                // 设置父级宽度, 以第一个子级 * 数量为准
                e.element.parent.width = e.element.parent.children[0].width * laneLength

                // 所有子级重新定位 全部以第一个为准, 第一个子级以父级为准
                e.element.parent.children.reduce((pre, shape) => {
                  if (shape.type === 'bpmn:Lane') {
                    // console.log(laneLength)
                    // shape.x = shape.parent.children[0].x + shape.parent.children[0].width * laneLength
                    // shape.x = shape.x - 30 + (shape.parent.children[0].width * (laneLength - 1))
                    // shape.y = shape.parent.y + 30
                  }
                })
              }
              // 拖动父级时reset设置父级宽度及定位
              if (e.element.type === 'bpmn:Participant' && e.element.children.length > 0) {
                let laneLength = e.element.children.reduce((pre, cur) => cur.type === 'bpmn:Lane' ? ++pre : pre, 0)
              }

              if (e.element.type === 'bpmn:Lane' || e.element.type === 'bpmn:Participant') {
                // 设置label文字位置
                let chatWidth = e.gfx.childNodes[0].childNodes[0].getAttribute('width')
                let textWidth = e.gfx.childNodes[0].getElementsByTagName('text')[0].getElementsByTagName('tspan')[0].innerHTML.length * 14 / 2
                e.gfx.childNodes[0].getElementsByTagName('text')[0].getElementsByTagName('tspan')[0].setAttribute('x', (chatWidth - textWidth) / 2)
                // 设置label编辑框的点击位置
                e.gfx.getElementsByClassName('djs-hit-all')[0].setAttribute('width', e.element.width)
                e.gfx.getElementsByClassName('djs-hit-all')[0].setAttribute('height', 30)
                // 设置横线分割线位置
                if (e.gfx.childNodes[0].getElementsByTagName('polyline')[0]) {
                  e.gfx.childNodes[0].getElementsByTagName('polyline')[0].setAttribute('points', '-30, 0, -30, ' + chatWidth)
                }
              }
              if (e.element.type === 'bpmn:ReceiveTask' || e.element.type === 'bpmn:BusinessRuleTask') {
                // let square = document.getElementsByClassName('djs-element djs-shape')[0]
                e.gfx.childNodes[0].getElementsByTagName('rect')[0].style.strokeWidth = 0
              }
              // if (element.type === 'bpmn:IntermediateThrowEvent') {//   //   console.log("初始化",square)//   if (square) {//     let node2 = square.childNodes[1]//     let node3 = square.childNodes[2]//     node2.setAttribute('width', 69)//     node2.setAttribute('height', 34)//     node3.setAttribute('x', 0)//     node3.setAttribute('y', 0)//     node3.setAttribute('width', 69)//     node3.setAttribute('height', 34)//   }// }// if (element.type === 'bpmn:ExclusiveGateway') {//   let square = document.getElementsByClassName('djs-element djs-shape')[0]//   if (square) {//     let node2 = square.childNodes[1]//     let node3 = square.childNodes[2]//     node2.setAttribute('width', 86)//     node2.setAttribute('height', 48)//     node3.setAttribute('x', 0)//     node3.setAttribute('y', 0)//     node3.setAttribute('width', 86)//     node3.setAttribute('height', 48)//   }// }// if (element.type === 'bpmn:DataObjectReference') {//   let square = document.getElementsByClassName('djs-element djs-shape')[0]//   if (square) {//     let node2 = square.childNodes[1]//     let node3 = square.childNodes[2]//     node2.setAttribute('width', 50)//     node2.setAttribute('height', 31)//     node3.setAttribute('x', 10)//     node3.setAttribute('y', 0)//     node3.setAttribute('width', 50)//     node3.setAttribute('height', 31)//   }// }
            } catch (e) {
              console.log('有异常啦', e)
            }
          } else if (eventType === 'element.click') {
            // that.bpmnModeler.saveXML({ format: true }, function (err, xml) {
            //   console.log(xml)
            // });
            // 重要
            if (e.element.type === 'bpmn:Lane') {
              // 点击时判断panel的拆分按钮是否要隐藏
              const styleEl = document.createElement('style')
              styleEl.type = 'text/css'
              const cssCode = `
                .djs-overlay-container .djs-overlays[data-container-id="${e.element.id}"] .bpmn-icon-lane-insert-below {
                  display: none;
                }`
              styleEl.appendChild(document.createTextNode(cssCode))

              // document.head.appendChild(styleEl); // 添加到文档头部
              document.body.appendChild(styleEl) // 添加到文档主体
            }
            // console.log('element.click', e.element)
            // } else if (eventType === 'element.dblclick') {
            //   console.log('element.dblclick', e.element)
            // } else if (eventType === 'element.updateLabel') {
            //   console.log('element.updateLabel', e.element)
            // } else if (eventType === 'import.parse.complete') {
            //   console.log('import.parse.complete', e.element)
            // } else if (eventType === 'element.create') {
            //   console.log('element.create', e.element)
          } else if (eventType === 'drag.move') {
            // 所有元素的拖拽初始化事件, 包括palette面板中的
            // console.log('drag.move', e)
            // console.log(e.shape.type)
            // e.shape.type 包含但不限于以下几种类型
            // bpmn:Task
            // bpmn:UserTask
            // bpmn:SubProcess
            // bpmn:DataObjectReference
            // bpmn:DataStoreReference
            // bpmn:Participant
            // 如果类型为 UserTask和SubProcess 需要处理一下css 横竖方向
            if (e.shape.type === 'bpmn:UserTask' || e.shape.type === 'bpmn:Task') {
            } else if (e.shape.type === 'bpmn:SubProcess') {
              let square = document.getElementsByClassName('djs-dragger')[0]
              let circle = document.getElementsByClassName('djs-dragger')[1]
              if (square) {
                // 设置外框大小
                square.getElementsByClassName('djs-visual')[0].getElementsByTagName('rect')[0].setAttribute('width', 200)
                square.getElementsByClassName('djs-visual')[0].getElementsByTagName('rect')[0].setAttribute('height', 350)
                // 设置内部start event位置
                // 默认原有transform="matrix(1 0 0 1 -135 -18)"
                circle.setAttribute('transform', 'matrix(1 0 0 1 -95 -75)')
              }
            } else if (e.shape.type === 'bpmn:Participant') {
              let node = document.getElementsByClassName('djs-dragger')[0]
              if (node) {
                node.classList.add('djs-dragger-rotate-participant')
              }
            }

          } else if (eventType === 'directEditing.activate') {
            // console.log('directEditing.activate', e)
            // console.log('directEditing.activate', e.active)
            // 点击泳道label修改名称时, 将输入框进行位移
            // console.log(document.getElementsByClassName("viewport")[0].getAttribute("transform"))
            let x = 0
            let y = 0
            let transform = document.getElementsByClassName('viewport')[0].getAttribute('transform')
            if (transform) {
              transform = transform.replace(/\)/g, '').replace(/\(/g, '').split(',')
              x += Number(transform[4])
              y += Number(transform[5])
            }
            // console.log(x, y)
            document.getElementsByClassName('djs-direct-editing-parent')[0].style.left = e.active.element.x + x + 'px'
            document.getElementsByClassName('djs-direct-editing-parent')[0].style.top = e.active.element.y + y + 'px'
            document.getElementsByClassName('djs-direct-editing-parent')[0].style.width = e.active.element.width + 'px'
          } else if (eventType === 'directEditing.complete') {
            // 重新初始化所有泳道label修改名称时的text元素宽度
            for (let key in elementRegistry._elements) {
              let node = elementRegistry._elements[key]
              let element = node.element
              if (element.type === 'bpmn:Participant' || element.type === 'bpmn:Lane') {
                // let djsVisual = node.gfx.getElementsByClassName("djs-visual")[0]
                let textNode = node.gfx.getElementsByClassName('djs-visual')[0].lastElementChild
                textNode.innerHTML = ''
                let txt = that.bpmnModeler.get('bpmnRenderer')._renderLabel(textNode, element.businessObject.name, {
                  box: {
                    height: 30,
                    width: element.width
                  },
                  align: 'center-middle',
                  style: {
                    fill: 'red'
                  }
                })
                textNode.innerHTML = txt.innerHTML
              } else if (element.type === 'label') {
                // let pNode = node.gfx.getElementsByClassName('djs-visual')[0].parentNode
                // console.log('pNode', pNode, pNode.getAttribute('isChange'))
                // if (pNode.getAttribute('isChange') !== 'true') {
                //   console.log('pNode.getAttribute(\'transform\');', pNode.getAttribute('transform'))
                //   let transform = pNode.getAttribute('transform')
                //   transform = transform.replace(/\)/g, '').replace(/\(/g, '').split(' ')
                //   console.log('transform', transform)
                //   pNode.setAttribute('transform', 'matrix(1 0 0 1 ' + Number(transform[4]) + ' ' + (Number(transform[5]) - 30) + ' )')
                //   pNode.setAttribute('isChange', true)
                // }
                // console.log('父级', pNode)
              }
            }
          }
        })
      })
    },
    addModelerListener() {
      const bpmnjs = this.bpmnModeler
      const modeling = bpmnjs.get('modeling')
      const that = this
      const events = ['shape.added', 'shape.move.end', 'shape.removed', 'shape.changed']
      events.forEach(function(event) {
        that.bpmnModeler.on(event, e => {
          var elementRegistry = bpmnjs.get('elementRegistry')
          var shape = e.element ? elementRegistry.get(e.element.id) : e.shape
          if (event === 'shape.added') {
            // 新建shape时设置大小
            if (shape.parent.parent == undefined && shape.type == 'bpmn:Participant') {
              shape.width = 300
              shape.height = 600
            } else if (shape.type === 'bpmn:Lane') {
              let laneLength = shape.parent.children.reduce((pre, cur) => cur.type === 'bpmn:Lane' ? ++pre : pre, 0)
              // 设置父级宽度, 以第一个子级 * 数量为准
              shape.parent.width = shape.parent.children[0].width * laneLength
              shape.parent.height = shape.parent.children[0].height + 30

              // modeling.resizeLane(shape.parent, {x: shape.parent.x, y: shape.parent.y, width: shape.parent.children[0].width * laneLength, height: shape.parent.children[0].height + 30})
              // modeling.resizeShape(shape.parent, {
              //   x: shape.parent.x, y: shape.parent.y, width: shape.parent.children[0].width * laneLength, height: shape.parent.children[0].height + 30
              // },{
              //   x: shape.parent.x, y: shape.parent.y, width: shape.parent.children[0].width * laneLength, height: shape.parent.children[0].height + 30
              // })
              // TODO setTimeout是不规范的, 临时解决问题
              setTimeout(() => {
                modeling.resizeShape(shape.parent, {
                  x: shape.parent.x,
                  y: shape.parent.y,
                  width: shape.parent.children[0].width * laneLength,
                  height: shape.parent.children[0].height + 30
                }, {
                  x: shape.parent.x,
                  y: shape.parent.y,
                  width: shape.parent.children[0].width * laneLength,
                  height: shape.parent.children[0].height + 30
                })
              }, 500)

              // 所有宽度 全部以第一个为准, 第一个子级以父级为准
              shape.x = shape.x - 30 + (shape.parent.children[0].width * (laneLength - 1))
              shape.y = shape.parent.y + 30
              shape.width = shape.parent.children[0].width
              shape.height = shape.parent.height - 30

              // create时手动隐藏子级panel的拆分按钮
              const styleEl = document.createElement('style')
              styleEl.type = 'text/css'
              const cssCode = `
                  .djs-overlay-container .djs-overlays[data-container-id="${e.element.id}"] .bpmn-icon-lane-insert-below {
                    display: none;
                  }
                  // .djs-overlay-container .djs-overlays[data-container-id="${e.element.id}"] .bpmn-icon-trash {
                  //   display: none;
                  // }`
              styleEl.appendChild(document.createTextNode(cssCode))

              // document.head.appendChild(styleEl); // 添加到文档头部
              document.body.appendChild(styleEl) // 添加到文档主体
            } else if (shape.type === 'bpmn:SubProcess') {
              // 设置框体位置
              setTimeout(() => {
                modeling.resizeShape(shape, {
                  x: shape.x, y: shape.y, width: shape.height, height: shape.width
                }, {
                  x: shape.x, y: shape.y, width: shape.height, height: shape.width
                })
              }, 10)
              // 设置框体内的StartEvent位置
              let startEvent = shape.children[0]
              // matrix(1 0 0 1 312 282)
              setTimeout(() => {
                modeling.resizeShape(startEvent, {
                  x: startEvent.x + 45, y: startEvent.y - 45, width: startEvent.width, height: startEvent.height
                }, {
                  x: startEvent.x + 45, y: startEvent.y - 45, width: startEvent.width, height: startEvent.height
                })
              }, 10)
            }

            // console.log('新增了shape')
            // } else if (event === 'shape.move.end') {
            //   console.log('移动了shape')
            // } else if (event === 'shape.removed') {
            //   console.log('删除了shape')

          } else if (event === 'shape.changed') {
            // console.log(event)
            // console.log(e)
            // console.log("============================")

            if (shape.type === 'bpmn:Lane') {
              let laneLength = shape.parent.children.reduce((pre, cur) => cur.type === 'bpmn:Lane' ? ++pre : pre, 0)
              // TODO setTimeout是不规范的, 临时解决问题
              setTimeout(() => {
                modeling.resizeShape(shape.parent, {
                  x: shape.parent.x,
                  y: shape.parent.y,
                  width: shape.parent.children[0].width * laneLength,
                  height: shape.parent.children[0].height + 30
                }, {
                  x: shape.parent.x,
                  y: shape.parent.y,
                  width: shape.parent.children[0].width * laneLength,
                  height: shape.parent.children[0].height + 30
                })
              }, 1)

              // 所有宽度 全部以第一个为准
              // 防止modeling.resizeShape循环触发shape.changed事件
              if (shape.x !== shape.x - 30 + (shape.parent.children[0].width * (laneLength - 1)) && shape.y !== shape.parent.y + 30) {
                setTimeout(() => {
                  // 查询x轴的偏移量
                  const index = shape.parent.children.findIndex(item => item.id === shape.id)
                  // console.log(index)
                  modeling.resizeShape(shape, {
                    x: shape.parent.x + shape.parent.children[0].width * index,
                    y: shape.parent.y + 30,
                    width: shape.width,
                    height: shape.height
                  }, {
                    x: shape.parent.x + shape.parent.children[0].width * index,
                    y: shape.parent.y + 30,
                    width: shape.width,
                    height: shape.height
                  })

                  // console.log("shape.parent.x", shape.parent.x)
                  // console.log("shape.parent.y", shape.parent.y)
                  // console.log("shape.x", shape.x)
                  // console.log("shape.y", shape.y)
                }, 1)
              }
            }

            // console.log('shape changed')
          }
        })
      })
    },

    beforeDestroy() {
      window.bpmnInstances = null
    },
    /**
     * 更新流程
     */
    updateHandle(data) {
      this.bpmnModeler.saveXML({ format: true }).then(({ xml }) => {
        updateNode({ processId: this.$route.params.id, bpmnXml: xml }).then(response => {
          this.$modal.msgSuccess('关联成功')
        })
      })
    }
  }
}
</script>
